home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 9 / CDACTUAL9.iso / share / Dos / VARIOS / pascal / SWAG9605.DDD / 0067_Convert USENET to QWK format.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-05-31  |  16.2 KB  |  697 lines

  1. {NEWSQWK.PAS}
  2.  
  3. {
  4.   Converts USENET files to QWK format ..
  5.  
  6.   You'll need PKZIP to use this.
  7.  
  8.   I use NXpress for my Newsgroup reader, in it saves it files with an
  9.   extension of .MBX.  If you newsreader saves in someother format, then
  10.   change the extension default at the front of the program.
  11.  
  12.   Perhaps you newsreader has a SAVEAS feature that allows you to download
  13.   all of the material and save it as a text file.  If so, you could use it.
  14.   Just save the files as SOMEFILE.MBX in the same DIR as this program,
  15.   and it'll create the QWK file for you.
  16.  
  17.   Gayle Davis 05/28/96
  18.  
  19. }
  20.  
  21. {$V-,S-,I-}
  22. {$M 16384,0,655360}   { no need to leave memory for PKZIP !!!
  23.                         see the EXECUTE procedure below and find out how !!}
  24.  
  25. USES
  26.   Dos, Crt, Upper, RLine;
  27.        { NOTE : Upper is in STRINGS.SWG
  28.                 RLINE is in TEXTFILE.SWG }
  29.  
  30. CONST
  31.      ControlHdr : ARRAY [1..11] OF STRING [30] = (
  32.  
  33.  {1} 'SOURCEWARE ARCHIVAL GROUP',  { change this to whatever you want ! }
  34.  {2} 'Goshen',                     { ditto }
  35.  {3} '875-8133',                   { ditto }
  36.  {4} 'Gayle Davis',                { ditto }
  37.  {5} '99999,SWAG',                 { ditto }
  38.  {6} '11-03-1993,04:41:37',        { this will get updated automatically }
  39.  {7} 'SWAG Genius',                { whatever pleases you ! }
  40.  {8} '',     { QMAIL Menu name ???                 }
  41.  {9} '0',    { allways ZERO ???                    }
  42. {10} '0',    { total number of messages in package }
  43. {11} '0');   { number of conferences-1 here        }
  44.              { next is 0 , then first conference   }
  45.  
  46. TYPE
  47.  
  48.   BlockArray   = ARRAY [1..128] OF CHAR;
  49.   CharArray    = ARRAY [1..6] OF CHAR;  { to read in chunks }
  50.   ControlArray = ARRAY [1..100] OF STRING [40]; { set to 100 conferences !!}
  51.   bsingle      = array [0..4] of byte;
  52.  
  53.   MSGDATHdr = RECORD
  54.     Status   : CHAR;
  55.     MSGNum   : ARRAY [1..7] OF CHAR;
  56.     Date     : ARRAY [1..8] OF CHAR;
  57.     Time     : ARRAY [1..5] OF CHAR;
  58.     UpTO     : ARRAY [1..25] OF CHAR;
  59.     UpFROM   : ARRAY [1..25] OF CHAR;
  60.     Subject  : ARRAY [1..25] OF CHAR;
  61.     PassWord : ARRAY [1..12] OF CHAR;
  62.     ReferNum : ARRAY [1..8] OF CHAR;
  63.     NumChunk : CharArray;
  64.     Alive    : BYTE;
  65.     LeastSig : BYTE;
  66.     MostSig  : BYTE;
  67.     Reserved : ARRAY [1..3] OF CHAR;
  68.   END;
  69.  
  70.   MBXHeader = RECORD
  71.    Xref     : STRING[70];
  72.    Path     : STRING;
  73.    From     : STRING[70];
  74.    Subject  : STRING[70];
  75.    Date     : STRING[40];
  76.    Lines    : WORD;
  77.    Status   : CHAR;
  78.    END;
  79.  
  80. CONST
  81.  
  82.      PKZIP   : PathStr = 'PKZIP.EXE';
  83.      QWKFile : PathStr = 'NEWS.QWK';
  84.  
  85. VAR
  86.  
  87.   MBXF        : TEXT;
  88.   QWKF        : FILE;
  89.   ControlF    : TEXT;
  90.  
  91.   FOL         : FileOfLinesPtr;
  92.   FOLPos      : LONGINT;
  93.  
  94.   SavePath,
  95.   SwagPath,
  96.   MBXFn,
  97.   MsgFName    : PATHSTR;
  98.  
  99.   TR          : SearchRec;
  100.  
  101.   ConfNum,
  102.   Number      : WORD;  { message number, conference number }
  103.  
  104.   MSGHdr      : MSGDatHdr;
  105.   ch          : CHAR;
  106.   count       : INTEGER;
  107.   chunks      : INTEGER;
  108.   ControlVal  : ControlArray;
  109.   ControlIdx  : BYTE;
  110.   ConfName,
  111.   WStr        : STRING;
  112.  
  113. FUNCTION TrimL (InpStr : STRING) : STRING; ASSEMBLER;
  114. ASM
  115.       PUSH   DS
  116.       LDS    SI, InpStr
  117.       XOR    AX, AX
  118.       LODSB
  119.       XCHG   AX, CX
  120.       LES    DI, @Result
  121.       INC    DI
  122.       JCXZ   @@2
  123.  
  124.       MOV    BL, ' '
  125.       CLD
  126. @@1 :  LODSB
  127.       CMP    AL, BL
  128.       LOOPE  @@1
  129.       DEC    SI
  130.       INC    CX
  131.       REP    MOVSB
  132.  
  133. @@2 :  XCHG   AX, DI
  134.       MOV    DI, WORD PTR @Result
  135.       SUB    AX, DI
  136.       DEC    AX
  137.       STOSB
  138.       POP    DS
  139. END;
  140.  
  141. FUNCTION TrimR (InpStr : STRING) : STRING;
  142.  
  143. VAR i : INTEGER;
  144.  
  145. BEGIN
  146.    i := LENGTH (InpStr);
  147.    WHILE (i >= 1) AND (InpStr [i] = ' ') DO
  148.       i := i - 1;
  149.    TrimR := COPY (InpStr, 1, i)
  150. END;
  151.  
  152. FUNCTION TrimB (InpStr : STRING) : STRING;
  153.  
  154. BEGIN
  155.  TrimB := TrimL (TrimR (InpStr) );
  156. END;
  157.  
  158. FUNCTION PadR (InpStr : STRING; FieldLen : BYTE) : STRING;
  159.   {-Return a string right-padded to length len with ch}
  160. VAR
  161.   o    : STRING;
  162.   SLen : BYTE ABSOLUTE InpStr;
  163. BEGIN
  164.   IF LENGTH (InpStr) >= FieldLen THEN
  165.     PadR := COPY (InpStr, 1, FieldLen)
  166.   ELSE BEGIN
  167.     o [0] := CHR (FieldLen);
  168.     MOVE (InpStr [1], o [1], SLen);
  169.     IF SLen < 255 THEN
  170.       FILLCHAR (o [SUCC (SLen) ], FieldLen - SLen, #32);
  171.     PadR := o;
  172.   END;
  173. END;
  174.  
  175.  
  176. FUNCTION GoodNumber (S : STRING) : BOOLEAN;
  177. VAR
  178.    Num  : LONGINT;
  179.    Code : WORD;
  180.  
  181. BEGIN
  182. Num := 0;
  183. VAL (S, Num, Code);
  184. GoodNumber := ( (Code = 0) AND (Num > 0) AND (S > '') );
  185. END;
  186.  
  187.  
  188. FUNCTION IntStr (Num : LONGINT; Width : BYTE; Zeros : BOOLEAN) : STRING;
  189. { Return a string value (width 'w')for the input integer ('n') }
  190.   VAR
  191.     Stg : STRING;
  192.   BEGIN
  193.     STR (Num : Width, Stg);
  194.     IF Zeros THEN BEGIN
  195.     FOR Num := 1 TO Width DO IF Stg [Num] = #32 THEN Stg [Num] := '0';
  196.     END ELSE Stg := TrimL (Stg);
  197.     IntStr := Stg;
  198.   END;
  199.  
  200.  FUNCTION GetStr (VAR InpStr : STRING; Delim : CHAR) : STRING;
  201.  
  202. VAR i : INTEGER;
  203. BEGIN
  204.    i := POS (Delim, InpStr);
  205.    IF i = 0 THEN
  206.    BEGIN
  207.       GetStr := InpStr;
  208.       InpStr := ''
  209.       END ELSE
  210.           BEGIN
  211.           GetStr := COPY (InpStr, 1, i - 1);
  212.           DELETE (InpStr, 1, i)
  213.           END
  214. END;
  215.  
  216. FUNCTION Str2LongInt (S : STRING; VAR I : LONGINT) : BOOLEAN;
  217.     {-Convert a string to an integer, returning true if successful}
  218.   VAR
  219.     code : WORD;
  220.   BEGIN
  221.     VAL (S, I, code);
  222.     IF code <> 0 THEN BEGIN
  223.       i := 0;
  224.       Str2LongInt := FALSE;
  225.     END ELSE
  226.       Str2LongInt := TRUE;
  227.   END;
  228.  
  229. FUNCTION GetNumber (VAR InpStr : STRING; Delim : CHAR) : LONGINT;
  230.  
  231. VAR S, S1 : STRING;
  232.     I    : LONGINT;
  233. BEGIN
  234.    I  := 0;
  235.    S1 := InpStr;
  236.    S  := GetStr (InpStr, Delim);
  237.    IF NOT GoodNumber (S) THEN InpStr := S1 ELSE
  238.    Str2LongInt (S, I);
  239.    GetNumber := I;
  240. END;
  241.  
  242.  
  243. FUNCTION NameOnly (FileName : PathStr) : PathStr;
  244. { Strip any path information from a file specification }
  245. VAR
  246.    Dir  : DirStr;
  247.    Name : NameStr;
  248.    Ext  : ExtStr;
  249. BEGIN
  250.    FSplit (FileName, Dir, Name, Ext);
  251.    NameOnly := Name;
  252. END {NameOnly};
  253.  
  254. FUNCTION SlashDate(AddCentury : BOOLEAN) : STRING; {10/08/88}
  255.  
  256. VAR
  257.   MonthName, dayname, yearname, dayofweekname : WORD;
  258.  
  259. BEGIN
  260.  
  261.   GETDATE (yearname, MonthName, dayname, dayofweekname);
  262.  
  263.   IF AddCentury THEN
  264.   SlashDate := IntStr (MonthName, 2, TRUE) + '/' +
  265.   IntStr (dayname, 2, TRUE) + '/' +
  266.   IntStr (yearname, 4, TRUE) ELSE
  267.  
  268.   SlashDate := IntStr (MonthName, 2, TRUE) + '/' +
  269.   IntStr (dayname, 2, TRUE) + '/' +
  270.   COPY (IntStr (yearname, 4, TRUE), 3, 2);
  271.  
  272. END;
  273.  
  274. FUNCTION PlainTime : STRING; {09:10:01}
  275.  
  276. VAR
  277.   Hr, Min, Sec, sec100 : WORD;
  278.  
  279. BEGIN
  280.   GETTIME (Hr, Min, Sec, sec100);
  281.   PlainTime := IntStr (Hr, 2, TRUE) + ':' +
  282.   IntStr (Min, 2, TRUE) + ':' +
  283.   IntStr (Sec, 2, TRUE);
  284.  
  285. END;
  286.  
  287. FUNCTION EraseFile ( S : PathStr ) : BOOLEAN ;
  288. VAR F : FILE;
  289. BEGIN
  290. EraseFile := FALSE;
  291. ASSIGN (F, S);
  292. RESET (F);
  293. IF IORESULT <> 0 THEN EXIT;
  294.   CLOSE (F);
  295.   ERASE (F);
  296.   EraseFile := (IORESULT = 0);
  297. END;
  298.  
  299. PROCEDURE ReallocateMemory(P : POINTER); ASSEMBLER;
  300. ASM
  301.   MOV  AX, PrefixSeg
  302.   MOV  ES, AX
  303.   MOV  BX, WORD PTR P+2
  304.   CMP  WORD PTR P,0
  305.   JE   @OK
  306.   INC  BX
  307.  
  308.  @OK:
  309.   SUB  BX, AX
  310.   MOV  AH, 4Ah
  311.   INT  21h
  312.   JC   @X
  313.   LES  DI, P
  314.   MOV  WORD PTR HeapEnd,DI
  315.   MOV  WORD PTR HeapEnd+2,ES
  316.  
  317.  @X:
  318. END;
  319.  
  320. FUNCTION EXECUTE(Name : PathStr ; Tail : STRING) : WORD; ASSEMBLER;
  321. ASM
  322.   {$IFDEF CPU386}
  323.   DB      66h
  324.   PUSH    WORD PTR HeapEnd
  325.   DB      66h
  326.   PUSH    WORD PTR Name
  327.   DB      66h
  328.   PUSH    WORD PTR Tail
  329.   DB      66h
  330.   PUSH    WORD PTR HeapPtr
  331.   {$ELSE}
  332.   PUSH    WORD PTR HeapEnd+2
  333.   PUSH    WORD PTR HeapEnd
  334.   PUSH    WORD PTR Name+2
  335.   PUSH    WORD PTR Name
  336.   PUSH    WORD PTR Tail+2
  337.   PUSH    WORD PTR Tail
  338.   PUSH    WORD PTR HeapPtr+2
  339.   PUSH    WORD PTR HeapPtr
  340.   {$ENDIF}
  341.   CALL ReallocateMemory
  342.   CALL SwapVectors
  343.   CALL DOS.EXEC
  344.   CALL SwapVectors
  345.   CALL ReallocateMemory
  346.   MOV  AX, DosError
  347.   OR   AX, AX
  348.   JNZ  @OUT
  349.   MOV  AH, 4Dh
  350.   INT  21h
  351.  
  352.  @OUT:
  353. END;
  354.  
  355.  
  356. PROCEDURE FindPKZip;
  357. VAR
  358.   S : PathStr;
  359. BEGIN
  360.   S := FSearch ('PKZIP.EXE', GetEnv ('PATH') );
  361.   IF S = '' THEN
  362.      BEGIN
  363.      WriteLn(#7,'You GOTTA have PKZIP somewhere on your PATH to do this !!');
  364.      HALT(1);
  365.      END;
  366.      PKZIP := FExpand (S);
  367. END;
  368.  
  369. PROCEDURE CleanUp;
  370. { clean up after ourselves }
  371. BEGIN
  372.   FINDFIRST ('*.NDX', $21, TR);
  373.   WHILE DosError = 0 DO
  374.         BEGIN
  375.         EraseFile(TR.NAME);
  376.         FINDNEXT (TR);
  377.         END;
  378.   EraseFile('MESSAGES.DAT');
  379.   EraseFile('CONTROL.DAT');
  380.  
  381. END;
  382.  
  383. PROCEDURE CreateControlDat;
  384. VAR
  385.     I : BYTE;
  386. BEGIN
  387.  
  388.      ControlHdr [ 6] := SlashDate(TRUE)+','+PlainTime;
  389.      ControlHdr [10] := IntStr (Count, 5, FALSE);
  390.      ControlHdr [11] := IntStr (PRED (ConfNum), 3, FALSE);
  391.  
  392.      ASSIGN (ControlF, 'CONTROL.DAT');
  393.      REWRITE (ControlF);
  394.      FOR I := 1 TO 11 DO
  395.          WRITELN (ControlF, ControlHdr [i]);
  396.      FOR I := 1 TO ControlIdx DO
  397.          WRITELN (ControlF, ControlVal [i]);
  398.      CLOSE (ControlF);
  399. END;
  400.  
  401. PROCEDURE CreateMessageDat;
  402. VAR
  403.     I    : BYTE;
  404.     Buff : BlockArray;
  405. BEGIN
  406.  
  407.   FILLCHAR (ControlVal, SIZEOF (ControlVal), #0);
  408.   FILLCHAR (Buff, SIZEOF (Buff), #32);
  409.   FILLCHAR (MsgHdr, SIZEOF (MsgHdr), #32);
  410.   ConfNum    := 0;
  411.   ControlIdx := 0;
  412.   Number     := 0;
  413.   ASSIGN (QWKF, 'MESSAGES.DAT');
  414.   REWRITE (QWKF, SIZEOF (MsgHdr) );
  415.   WStr := 'NEWS TO QWK (c) 1996 GDSOFT';
  416.   FOR I := 1 TO LENGTH (WStr) DO Buff [i] := WSTR [i];
  417.   BLOCKWRITE (QwkF, Buff, 1);
  418. END;
  419.  
  420. FUNCTION ArrayTOInteger (B : CharArray; Len : BYTE) : LONGINT;
  421.  
  422. VAR I : BYTE;
  423.     S : STRING;
  424.     E  : INTEGER;
  425.     T  : INTEGER;
  426.  
  427. BEGIN
  428.     S := '';
  429.     FOR I := 1 TO PRED (Len) DO IF B [i] <> #32 THEN S := S + B [i];
  430.     VAL (S, T, E);
  431.     IF E = 0 THEN ArrayToInteger := T;
  432. END;
  433.  
  434. PROCEDURE GetNewsGroupHeader(VAR NGH : MBXHeader);
  435.  
  436. VAR
  437.    Junk : STRING;
  438.  
  439. BEGIN
  440.      WHILE POS('STATUS:',UpCaseStr(FOL^.LastLine)) = 0 DO
  441.          BEGIN
  442.          FOL^.SeekLine(FOLPos);
  443.          INC(FOLPos);
  444.          IF POS('XREF:',UpCaseStr(FOL^.LastLine)) > 0 THEN
  445.             NGH.XRef := TrimB(COPY(FOL^.LastLine,6,$FF));
  446.          IF POS('PATH:',UpCaseStr(FOL^.Lastline)) > 0 THEN
  447.             NGH.Path := TrimB(COPY(FOL^.LastLine,6,$FF));
  448.          IF POS('FROM:',UpCaseStr(FOL^.Lastline)) > 0 THEN
  449.             NGH.From := TrimB(COPY(FOL^.LastLine,6,$FF));
  450.          IF POS('SUBJECT:',UpCaseStr(FOL^.Lastline)) > 0 THEN
  451.             NGH.Subject := Trimb(COPY(FOL^.LastLine,9,$FF));
  452.          IF POS('DATE:',UpCaseStr(FOL^.Lastline)) > 0 THEN
  453.             NGH.Date := Trimb(COPY(FOL^.LastLine,6,$FF));
  454.          IF POS('LINES:',UpCaseStr(FOL^.Lastline)) > 0 THEN
  455.             BEGIN
  456.             Junk := GetStr(FOL^.LastLine,#32);
  457.             NGH.Lines := GetNumber(FOL^.LastLine,#32);
  458.             END;
  459.          IF POS('STATUS:',UpCaseStr(FOL^.Lastline)) > 0 THEN
  460.             NGH.STATUS := 'S';
  461.          END;
  462. END;
  463.  
  464. PROCEDURE ReadMessage(HdrPos : LONGINT);
  465. VAR
  466.  
  467.   HDR    : MsgDatHdr;
  468.   Block  : BlockArray;
  469.   EndPos : LONGINT;
  470.   Chunks : LONGINT;
  471.   J,K    : INTEGER;
  472.   I,SFOL : LONGINT;
  473.   NS     : STRING;
  474.   NGH    : MBXHeader;
  475.  
  476.   PROCEDURE MoveDataToBlock (Start, Len : BYTE; S : STRING; VAR Block : BlockArray);
  477.   VAR I, K : BYTE;
  478.  
  479.   BEGIN
  480.       K := 0;
  481.       FOR I := Start TO PRED (Start + Len) DO
  482.           BEGIN
  483.           INC (k);
  484.           Block [i] := S [k];
  485.           END;
  486.   END;
  487.  
  488.  
  489.   PROCEDURE WriteHeader;
  490.   BEGIN
  491.   { write the header out }
  492.   Seek(QwkF,HdrPos);
  493.   FillChar(Block,SizeOf(Block),#32);
  494.   MoveDataToBlock(  2, 7,PadR(IntStr(Number,7,FALSE),7),Block); { number }
  495.   MoveDataToBlock(  9, 8,SlashDate(FALSE),Block);               { date }
  496.   MoveDataToBlock( 17, 5,PlainTime,Block);                      { Time }
  497.   MoveDataToBlock( 22,25,PadR(ControlHdr[4],25),Block);               { To   }
  498.   MoveDataToBlock( 47,25,PadR(NGH.FROM,25),Block);              { From }
  499.   MoveDataToBlock( 72,25,PadR(NGH.Subject,25),Block);           { Subj }
  500.   MoveDataToBlock( 97,20,PadR('IMPORT',20),Block);              { Confname }
  501.   MoveDataToBlock(117, 6,PadR(IntStr(Chunks,6,FALSE),6),Block); { Numpacs }
  502.   MoveDataToBlock(124, 1,Chr(64),Block);
  503.   BlockWrite(QwkF,Block,1);
  504.   END;
  505.  
  506.   PROCEDURE WriteBlock;
  507.   BEGIN
  508.        BLOCKWRITE (QwkF, Block, 1);
  509.        FILLCHAR (Block, SIZEOF (Block), #32);
  510.        INC (chunks);  { increment block count }
  511.        k := 0;
  512.   END;
  513.  
  514.   PROCEDURE ProcessLine;
  515.   VAR
  516.      c : BYTE;
  517.   BEGIN
  518.        FOR c := 1 TO LENGTH(FOL^.LastLine) DO
  519.            BEGIN
  520.            INC (k);
  521.            {
  522.            IF FOL^.LastLine [c] = #13 THEN
  523.               BEGIN
  524.               Block [k] := #227;
  525.               INC (c);
  526.               END ELSE Block [k] := FOL^.LastLine [c];
  527.            }
  528.            Block[k] := FOL^.Lastline[c];
  529.            IF k = 128 THEN WriteBlock;
  530.  
  531.            END; { for }
  532.  
  533.       { write end of line }
  534.       INC(k);
  535.       Block[k] := #227;
  536.       IF k=128 THEN WriteBlock;
  537.   END;
  538.  
  539. BEGIN
  540.  
  541.   SFOL := SUCC(FOLPos);
  542.  
  543.   { read the header block }
  544.   GetNewsGroupHeader(NGH);
  545.  
  546.   { fill QWK Header with info }
  547.  
  548.   FILLCHAR (Block, SIZEOF (Block), #32);
  549.   FILLCHAR(Hdr,SizeOF(Hdr),#0);
  550.  
  551.   { write the header out }
  552.   chunks := 1;  { number packs }
  553.   INC(Number);  { update message number }
  554.  
  555.    { write the header to our QWK file }
  556.    WriteHeader;
  557.  
  558.    { write the blocks out }
  559.    K := 0;
  560.    FILLCHAR (Block, SIZEOF (Block), #32);
  561.  
  562.    FOR I := FOLPos TO FOLPos + NGH.Lines DO
  563.        BEGIN
  564.        FOL^.SeekLine(i);
  565.        ProcessLine;
  566.        END;
  567.  
  568.   J := I; { save the FOLPos for later }
  569.  
  570.   { write the original header out }
  571.   FOL^.LastLine := ' ';
  572.   ProcessLine;
  573.   FOL^.LastLine := 'Original Header:';
  574.   ProcessLine;
  575.   FOL^.LastLine := ' ';
  576.   ProcessLine;
  577.  
  578.   FOR I := SFOL TO FOLPos DO
  579.       BEGIN
  580.       FOL^.Seekline(i);
  581.       ProcessLine;
  582.       END;
  583.  
  584.   IF k > 0 THEN WriteBlock;
  585.   FOLPos := j; { update the position in the file }
  586.  
  587.   EndPos := FilePos(QwkF);
  588.  
  589.   { update the header }
  590.   WriteHeader;
  591.   SEEK(QwkF, EndPos);
  592.  
  593. END;
  594.  
  595. PROCEDURE ProcessUseNetFile (FN : PathStr);
  596. { this is the heart !!  Read messages from MBX file and save in QWK file }
  597. VAR
  598.     ndxF : File;
  599.     b    : bSingle;
  600.     r    : REAL;
  601.     n    : LONGINT;
  602.  
  603.     { converts TP real to Microsoft 4 bytes single .. GOOFY !!!! }
  604.     procedure real_to_msb (preal : real; var b : bsingle);
  605.     var
  606.          r : array [0 .. 5] of byte absolute preal;
  607.     begin
  608.          b [3] := r [0];
  609.          move (r [3], b [0], 3);
  610.     end; { procedure real_to_msb }
  611.  
  612.  
  613. BEGIN
  614.  
  615.   WriteLn('Process .. ',FN);
  616.  
  617.   { create the NDX file }
  618.   ASSIGN  (ndxF,IntStr(ConfNum,3,TRUE)+'.NDX');
  619.   REWRITE (ndxF,1);
  620.  
  621.   WHILE (FOLPos < FOL^.Totallines) DO
  622.         BEGIN
  623.  
  624.         n := SUCC(FilePos(QwkF));      { ndx wants the RELATIVE position }
  625.         r := N;                        { make a REAL                     }
  626.         REAL_TO_MSB(r,b);              { convert to MSB format           }
  627.         BLOCKWRITE(ndxF,B,SizeOf(B));  { store it                        }
  628.  
  629.         WriteLn('Process message .. ',IntStr(Number+1,5,FALSE));
  630.         ReadMessage(PRED(n));
  631.         INC(Count);
  632.         END;
  633.  
  634.   CLOSE (NdxF);
  635.  
  636.   { update the CONTROL file array }
  637.   INC (ControlIdx);
  638.   ControlVal [ControlIdx] := IntStr (ConfNum, 3, TRUE);
  639.   INC (ControlIdx);
  640.   ControlVal [ControlIdx] := ConfName;
  641.   INC (ConfNum);
  642.  
  643. END;
  644.  
  645. PROCEDURE GetConferenceName;
  646.  
  647. VAR
  648.    Junk : STRING;
  649.  
  650. BEGIN
  651.      WHILE POS('NEWSGROUPS:',UpCaseStr(FOL^.LastLine)) = 0 DO
  652.          BEGIN
  653.          FOL^.SeekLine(FOLPos);
  654.          INC(FOLPos);
  655.          END;
  656. Junk     := GetStr(FOL^.LastLine,' ');
  657. ConfName := TrimB(FOL^.Lastline);
  658. FOLPos   := 1;
  659. END;
  660.  
  661. BEGIN
  662.  
  663.   ClrScr;
  664.  
  665.   IF ParamCount > 0 THEN MBXfn := FExpand(ParamStr(1)) ELSE MBXfn := '*.MBX';
  666.  
  667.   EraseFile(QWKFile);  { make sure we don't have one yet }
  668.  
  669.   FindPkZip;
  670.  
  671.   CreateMessageDat;
  672.  
  673.   Count := 0;  { total messages in package }
  674.  
  675.   { process all the files that we find with the extension }
  676.   FINDFIRST (MBXFn, $21, TR);
  677.   WHILE DosError = 0 DO
  678.         BEGIN
  679.         NEW(FOL, Init(TR.Name, 1024));
  680.         FOLPos := 1;  { current position in RLINE array }
  681.         GetConferenceName;
  682.         ProcessUseNetFile (TR.Name);
  683.         DISPOSE (FOL, Done);
  684.         FindNext(TR);
  685.         END;
  686.  
  687.   CLOSE (QwkF);
  688.  
  689.   CreateControlDat;
  690.  
  691.   Execute(PKZIP,' -ex '+QWKFile+' *.NDX MESSAGES.DAT CONTROL.DAT');
  692.  
  693.   CleanUp;
  694.  
  695.  
  696. END.
  697.